Московский Авиационный Институт
(Технический университет)
Курсовой проект
Студент: Кузнецов А.В. 06-321
Москва 2003
Table of Contents
2
Модули 3
error.h 3
error.c 3
types.h 3
parse.h 3
parse.c 3
select.h 4
select.c 5
show.h 8
show.c 8
sort.h 9
sort.c 9
stdio.h 17
stdio.c 17
stdlib.h 18
stdlib.c 18
Stage.c 20
Разбора ввода пользователя
Проверка параметров
Получение данных из файлов
Сортировка
Вывод
Ошибок
// установка текста ошибки
void seterror(const char*);
// получить текст ошибки
const char* geterror();
#include "error.h"
#include "stdlib.h"
char m_errortext[256]={0};
void seterror(const char* p)
{
_strcpy(m_errortext,p);
}
const char* geterror()
{
return m_errortext;
}
#ifndef __TYPES_H
#define __TYPES_H
typedef char fieldname[64];
typedef char tablename[64];
typedef char field[512];
#endif
// parse - функция разберает входную строчку
// fieldname *flds - список полей
// int fldmax - максимальное количество полей
// tablename* tbls - входные такблицы(файлы)
// int tblmax - максимальное количество таблиц
// fieldname *ord - поле сортировки
// const char* cmdline - строчка для разбора
int parse(fieldname *flds,int fldmax,tablename* tbls,int tblmax,fieldname *ord,const char* cmdline);
#include "types.h"
#include "parse.h"
#include "stdlib.h"
#include "error.h"
#define ISLETTER(x) ((x>='a'&&x<='z')||(x>='A'&&x<='Z'))
#define ISNUMBER(x) (x>='0'&&x<='9')
#define ISLETNUM(x) (ISLETTER(x)||ISNUMBER(x)||x=='*'||x=='_'||x=='.')
// получает целое слово
const char* getnexttok(const char* cmdline,char *buf)
{
if(cmdline==0||*cmdline==0)
return 0;
while(!ISLETNUM(*cmdline))
cmdline++;
while(ISLETNUM(*cmdline))
*buf++=*cmdline++;
*buf=0;
return cmdline;
}
int parse(fieldname *flds,int fldsmax,tablename *tbls,int tblmax,fieldname *ord,const char* cmdline)
{
char buf[50];
cmdline=getnexttok(cmdline,buf);
if(_streq(buf,"select")==0)
{
seterror("cmd line must begin from 'select'");
return 0;
}
while((cmdline=getnexttok(cmdline,buf))!=0&&!_streq(buf,"from"))
{
if(fldsmax--==0)
{
seterror("flelds overflow");
return 0;
}
_strcpy(*flds++,buf);
}
while((cmdline=getnexttok(cmdline,buf))!=0&&!_streq(buf,"order"))
{
if(tblmax--==0)
{
seterror("tables overflow");
return 0;
}
_strcpy(*tbls++,buf);
}
if((cmdline=getnexttok(cmdline,buf))==0||!_streq(buf,"by"))
{
seterror("order by not found");
return 0;
}
if((cmdline=getnexttok(cmdline,buf))!=0)
{
_strcpy(*ord,buf);
}
return 1;
}
// модуль работы с базой данных (файлами)
// select - производит запрос по полям (flds) из указанных таблиц (tbl) (файлов)
// и помещает результат в data, ограниченный datamax
int select(int *selectfieldsidx,int selectfieldsidxcount,tablename *tbl,field *data,int datamax);
// нормализует параметры для передачи их в функции запроса
int normalizeparams(fieldname* selectfields,fieldname* orderfield,tablename *tbl,int* selectfieldsidx,int *selectfieldscount,int *orderfieldidx);
#include "types.h"
#include "select.h"
#include "error.h"
#include "stdlib.h"
#include "stdio.h"
// assist {
// чтение одного елемента из входного файла
// return:
// 1 чтение успешно
// 0 чтение строчку заверешено
// -1 конец файла
int readline(char* p,int max,FILE* f)
{
int c;
while((c=fgetc(f))!=EOF)
{
if(c==0xa)
{
*p=0;
return 0;
}
if(c==';')
{
*p=0;
return 1;
}
if(!--max)
{
*p=0;
return 1;
}
*p++=c;
}
return -1;
}
// чтение заголовков из файла
int readheaders(FILE* f,fieldname* headers,int headersmax)
{
int i=0;
int read=1;
while(read==1)
{
read=readline(*headers++,sizeof(fieldname),f);
if(i>=headersmax)
{
seterror("max headers reach");
return -1;
}
i++;
}
if(i==0)
{
seterror("no headers read");
return -1;
}
return i;
}
// чтение поля из файла
int readfield(field* p,FILE* f)
{
return readline((char*)p,sizeof(field),f);
}
// чтение из файла всех полей.
// selectfieldsidx - индексы полей
// selectfieldsidxcount - количество полей
// tbl - имя таблицы
// *data выходные данные (они содержаться в файле)
// datamax - объем буфера
int readfile(int *selectfieldsidx,int selectfieldsidxcount,tablename *tbl,field *data,int datamax)
{
int dataleft=datamax;
FILE *f=fopen(*tbl,"r");
fieldname headers[32]={0};
int headersmax=sizeof(headers)/sizeof(fieldname);
int i;
field fld;
if(f==0)
{
seterror("can't open input file");
return -1;
}
if(readheaders(f,headers,headersmax)==-1)
return -1;
while(!feof(f))
{//читаю все строчки
int read=1;
i=0;
while(read==1)
{
//читаю пока строка содержит ячейки
read=readfield(&fld,f);
if(findinnumarray(selectfieldsidx,selectfieldsidxcount,i)!=-1)
{//нужно добавить в считанные данные
if(dataleft--==0)
{
seterror("data overflow");
return -1;
}
_strcpy(*data++,fld);
}
i++;
}
}
fclose(f);
return datamax-dataleft;
}
// } assist
int select(int *selectfieldsidx,int selectfieldsidxcount,tablename *tbl,field *data,int datamax)
{
int total=0;
while(**tbl)
{
int read=readfile(selectfieldsidx,selectfieldsidxcount,tbl,data,datamax);
if(read==-1)
return -1;
data+=read;
datamax-=read;
total+=read;
tbl++;
}
return total;
}
int normalizeparams(fieldname* selectfields,fieldname* orderfield,tablename *tbl,int* selectfieldsidx,int *selectfieldscount,int *orderfieldidx)
{
int ret=1;
FILE *f=0;
int i;
int star=0;
*orderfieldidx=-1;
{
fieldname* fld=selectfields;
i=0;
while(**fld!=0)
{
if(_streq(*fld,"*"))
{
star++;
}
i++;
fld++;
}
if(star>1)
{
seterror("more that one '*'");
goto error;
}
if(star==1&&i!=1)
{
seterror("have '*' with other fields");
goto error;
}
}
while(**tbl!=0)
{
fieldname headers[32]={0};
int headersmax=sizeof(headers)/sizeof(fieldname);
int headerscount;
f=fopen(*tbl,"r");
if(f==0)
{
seterror("can't open input file");
goto error;
}
if((headerscount=readheaders(f,headers,headersmax))==-1)
goto error;
if(star==0)
{
*selectfieldscount=0;
for(i=0;i<headerscount;i++)
{
int *selectfieldsidx_itr=selectfieldsidx;
fieldname* fld=selectfields;
while(**fld!=0)
{
if(_stringformatcmp(headers[i],*fld)==0)
{
*selectfieldsidx_itr++=i;
(*selectfieldscount)++;
}
fld++;
}
}
}else
{
int *selectfieldsidx_itr=selectfieldsidx;
*selectfieldscount=headerscount;
for(i=0;i<headerscount;i++)
{
*selectfieldsidx_itr++=i;
}
}
for(i=0;i<*selectfieldscount;i++)
{
if(_stringformatcmp(headers[selectfieldsidx[i]],*orderfield)==0)
*orderfieldidx=selectfieldsidx[i];
}
fclose(f);
tbl++;
}
if(*orderfieldidx==-1)
{
seterror("order field not found");
goto error;
}
goto exit;
error:
ret=0;
exit:
if(f!=0)
fclose(f);
return ret;
}
// показывает результат операции, записывая его ввыходной файл
int show(field *data, int *selectfieldsidx, int selectfieldscount,int orderfieldidx,const char* filename);
#include "types.h"
#include "show.h"
#include "stdio.h"
#include "stdlib.h"
int show(field *data, int *selectfieldsidx, int selectfieldscount,int orderfieldidx, const char* filename)
{
int keyfieldnum=findinnumarray(selectfieldsidx,selectfieldscount,orderfieldidx);
FILE *f=fopen(filename,"w");
/*
while(**flds2!=0)
{
fwritestring(f,*flds2++);
fwritestring(f,";");
}
fwritestring(f,"\n");
*/
while(**data!=0)
{
int i;
fwritestring(f,*(data+keyfieldnum));
fwritestring(f," -> ;");
for(i=0;i<selectfieldscount;i++)
{
fwritestring(f,*data++);
fwritestring(f,";");
}
fwritestring(f,"\n");
}
fclose(f);
return 1;
}
// data - что сортируем
// flds - заголовки. по их полчисеству определяю размер столбцов
// orderfield - заголовок сортировки
int sort(field *data,int datasize,int *selectfieldsidx,int selectfieldscount,int orderfieldidx);
#include "types.h"
#include "sort.h"
#include "stdlib.h"
// количество лент
#define T 6
// физическое устройство
int* tape[T];
// головка записи\четния
int* tape_ptr[T];
// запись на ленту
void tapewrite(int tapeindex, int what)
{
*tape_ptr[tapeindex]=what;
tape_ptr[tapeindex]++;
}
// чтение с ленты
int taperead(int tapeindex)
{
return *tape_ptr[tapeindex]++;
}
// переметывает линту
void tapeinit(int tapeindex)
{
tape_ptr[tapeindex]=tape[tapeindex];
}
// перематывает ленты
void tapesinit()
{
int i=T;
for(i=0;i<T;i++)
tapeinit(i);
}
// подает питание на устройство, вставляет лену указанной длинны
void tapescreate(int datasize)
{
int i;
for(i=0;i<T;i++)
{
tape[i]=(int*)malloc(datasize*sizeof(int));
tape_ptr[i]=tape[i];
}
}
// выключает устройство
void tapesclose()
{
int i;
for(i=0;i<T;i++)
free(tape[i]);
}
// функция сравнения полей
// результат указывает на наименьшее поле (-1 0 1)
int compare(field* data, int idx1,int idx2)
{
const char* p1,*p2;
if(idx1==-1&&idx2==-1)
return 0;
if(idx1==-1)
return 1;
if(idx2==-1)
return -1;
if(idx1==idx2)
return 0;
p1=data[idx1];
p2=data[idx2];
if(*p1=='"'&&*p2=='"')
{// сравнение строк
return _strcmp(p1,p2);
}else if(*p1!='"'&&*p1!='"')
{// сравнение числе
double fp1=atof(p1),fp2=atof(p2);
if(fp1==fp2)
return 0;
return fp1<fp2?-1:1;
}else
{// операция не определена, идет сравнение строки с числом
return 0;
}
}
// сравнивает поля
void sortfields(field* data,int* idx,int datacount)
{
int i,ii;
restart:
for(i=0;i<datacount;i++)
{
for(ii=i+1;ii<datacount;ii++)
{
if(idx[i]==-1||idx[ii]==-1)
continue;
if(compare(data,idx[i],idx[ii])>0)
{
int bak;
bak=idx[i];
idx[i]=idx[ii];
idx[ii]=bak;
goto restart;
}
}
}
}
// чтение с учетом фиктивных отрезков
int taperead_f(int *D,int *F,int *A,int *C,int *tape_logical,int tapeindex)
{
int value;
C[tape_logical[tapeindex]]++;
D[tape_logical[tapeindex]]--;
value=taperead(tape_logical[tapeindex]);
if(value==-1)
F[tape_logical[tapeindex]]--;
return value;
}
// запись на касету, работает с фиктивными отрекзами
void tapewrite_f(int*D,int *F,int *tape_logical,int tapeindex,int value)
{
D[tape_logical[tapeindex]]++;
if(value==-1)
{
F[tape_logical[tapeindex]]++;
}
{
tapewrite(tape_logical[tapeindex],value);
}
}
// D[] - количество отрезков на ленте (включая фиктивные)
// F[] - количество фиктивных отрезков
// A[] - длинна отрезка на ленте
// C[] - распределение текущее (сколько отрезков прочитано)
// n - касета результата, она же максимальное количесвтво касет для текущего распределния
// функция делает одно распределение. если во время него появилась пустая касета
// возвращаеться 1, и вообще возвращаеться количество путых касет
int cascadedistribution(field* data,int *D,int *F,int *A,int *C,int n,int *tape_logical,int tapecount)
{
int tapeindex;
int min;
int *tapebuf=malloc(sizeof(int)*tapecount);
int *tapeaccess=malloc(sizeof(int)*tapecount);
int ret = 0;
for(tapeindex=0;tapeindex<n;tapeindex++)
{
tapebuf[tape_logical[tapeindex]]=taperead_f(D,F,A,C,tape_logical,tapeindex);
tapeaccess[tape_logical[tapeindex]]=1;
if(D[tape_logical[tapeindex]]==0)
ret++;
}
{
loop:
min=-1;
// min примет другое значение только если есть еще блоки для сортировки.
// это означает что либо буфер не пуст, либо за эти проходы не считались все данные
// C[] < A[] (считанных отрезков меньше чем их длины)
// поиск минимального осуществляеться только в тех массивах где нет максимального числа
// прочитанных блоков
for(tapeindex=0;tapeindex<n;tapeindex++)
{
if(!tapeaccess[tape_logical[tapeindex]])
continue;
if(min==-1)
{
min=tapeindex;
continue;
}
if(compare(data,tapebuf[tape_logical[tapeindex]],tapebuf[tape_logical[min]])<0)
min=tapeindex;
}
// запись найденого елемента
if(min!=-1)
{
// записывую на ленту выхода значение минимального елемента
tapewrite_f(D,F,tape_logical,n,tapebuf[tape_logical[min]]);
// только если длинна считанного отрезка не больше его максимальной длинны
// читаю следующий отрезок.
// по идее требуеться проверить наличие елементов для чтение, но эта проверка
// автоматически проходит на наличие максимальной длинны (длинна отрезка не
// может превышать количство болков, она завязана на число Фибаначи)
if(C[tape_logical[min]]<A[tape_logical[min]])
{
tapebuf[tape_logical[min]]=taperead_f(D,F,A,C,tape_logical,min);
if(D[tape_logical[min]]==0)
ret++;
}else
tapeaccess[tape_logical[min]]=0;
goto loop;
}
}
free(tapebuf);
free(tapeaccess);
return ret;
}
// n-путевое силяние
// путевое слияние
// функция повторяет распределение пока нет пустой касеты
// если распределение завершилось 1
int cascadepathlink(field* data,int*D,int *F,int *A,int n,int *tape_logical,int tapecount)
{
// n = куда лить.
// n-1 - максимальное значение
int * C=malloc(sizeof(int)*tapecount);
//int i;
int ret=0;
int code=0;
while(1)
{
_memset(C,0,sizeof(int)*tapecount);
switch(cascadedistribution(data,D,F,A,C,n,tape_logical,tapecount))
{
case 0:
break; // goto looop
case 1:
goto exit;
default: //if(code>1)
ret=1;
goto exit;
}
}
exit:
free(C);
return ret;
}
// функция делает проход, пока не опустеет посделняя касета
void cascadepass(field* data,int *D,int *F,int* A,int *tape_logical,int tapecount)
{
int i;
for(i=tapecount-1;i>0;i--)
{
tapeinit(tape_logical[i]);
if(cascadepathlink(data,D,F,A,i,tape_logical,tapecount))
break;
}
}
#ifdef _DEBUG
#pragma comment(lib,"kernel32.lib")
#include <stdlib.h>
void __stdcall OutputDebugStringA(const char* lpOutputString);
void sprintf(char *, const char *, ...);
void tapesdump(field* data,int *D,int *F,int* A,int *tape_logical,int tapecount)
{
int casette;
tapesinit();
for(casette=0;casette<T;casette++)
{
int element;
char buf[1024];
sprintf(buf,"Casette %d (отрезков: %d, фиктивных: %d, длинна: %d)\n",casette,D[casette],F[casette],A[casette]);
OutputDebugStringA(buf);
for(element=0;element<D[casette];element++)
{
int value=taperead(casette);
sprintf(buf,"\t%d - '%s'(idx:%d)\n",element,value==-1?"":data[value],value);
OutputDebugStringA(buf);
if(div(element+1,A[casette]).rem==0)
OutputDebugStringA("\n");
}
}
}
#else
#define
tapesdump(data,D,F,A,tape_logical,tapecount) (void)0
#endif
// первое распределение фибоначи
int fibonacheinit(int *f,int *tape_logical,int tapecount)
{
int i,total=0;
for(i=0;i<tapecount-1;i++)
{
f[tape_logical[i]]=1;
total+=f[tape_logical[i]];
}
return total;
}
// получение распределения фибоначи
int fibonachenext(int *f,int *tape_logical,int tapecount)
{
// 0 1 2 3 4 5
// physical
// 0 0 0 0 0 0
// 1 1 1 1 1 -
// - 1 2 3 4 5
// 15 14 12 9 5 -
// logical
// 0 0 0 0 0 0
// 1 1 1 1 1 -
// 5 4 3 2 1 -
// 15 14 12 9 5 -
int i,total=0;
int* fnew;
fnew=malloc(sizeof(int)*tapecount);
_memset(fnew,0,sizeof(int)*tapecount);
// здесь происходит обращение не к f[tape_logical[0]] поскольку
// сейчас касеты уже инвертированы
fnew[tape_logical[1]]=f[tape_logical[0]];
total=fnew[tape_logical[1]];
for(i=2;i<tapecount;i++)
{
fnew[tape_logical[i]]=fnew[tape_logical[i-1]]+f[tape_logical[i-1]];
total+=fnew[tape_logical[i]];
}
_memcpy(f,fnew,sizeof(int)*tapecount);
free(fnew);
return total;
}
// логичесвое инверсирование касет
void tapesinvert(int *tape_logical,int tapecount)
{
int i;
for(i=0;i<tapecount/2;i++)
{
int bak;
bak=tape_logical[i];
tape_logical[i]=tape_logical[tapecount-1-i];
tape_logical[tapecount-1-i]=bak;
}
}
// сброс логических касет
void tapesreset(int *tape_logical,int tape_count)
{
int i;
for(i=0;i<tape_count;i++)
tape_logical[i]=i;
}
int sort(field *data,int datasize,int *selectfieldsidx,int selectfieldscount,int orderfieldidx)
{
const int linecount = datasize/selectfieldscount;
// логическое устройство
int tape_logical[T];
// количество уровней распределения
int l = 0;
// количество отрезков на ленто протяжном устройстве
int D[T]={0};
// количество фиктивных отрезков
int F[T]={0};
int keyfieldnum=findinnumarray(selectfieldsidx,selectfieldscount,orderfieldidx);
tapescreate(1000);
tapesreset(tape_logical,T);
// спецальное распредлеение
{
int A[T]={0};
int offset=0;
// получаю конечное распределение фибоначи, к которому стремлюсь
int total=fibonacheinit(A,tape_logical,T);
l=1;
while(total<linecount)
{
total=fibonachenext(A,tape_logical,T);
tapesinvert(tape_logical,T);
l++;
}
for(offset=keyfieldnum;offset<datasize;offset+=selectfieldscount)
{
// ищу место куда можно положить данные
{
int i;
for(i=0;i<T;i++)
{
if(D[tape_logical[i]]<A[tape_logical[i]])
{
tapewrite_f(D,F,tape_logical,i,offset);
break;
}
}
}
}
// после распределения нужно забить числа фиктивных отрезков
// в соответствии с числами фибоначи, так же привести D (кол
// ичество отрезков на лентах включая фиктивные отрезки) в
// соответсвтии с последним распределением
{
int i,offset;
for(offset=linecount;offset<total;offset++)
{
for(i=0;i<T;i++)
{
if(D[tape_logical[i]]<A[tape_logical[i]])
{
tapewrite_f(D,F,tape_logical,i,-1);
}
}
}
}
}
// каскадное слияние
{
// требуеться числа для распределения фибонаци, начальние значения отрезков по
// лентам.
int A[T]={0};
fibonacheinit(A,tape_logical,T);
while(l--)
{
tapesdump(data,D,F,A,tape_logical,T);
tapesinit();
cascadepass(data,D,F,A,tape_logical,T);
fibonachenext(A,tape_logical,T);
tapesinvert(tape_logical,T);
tapesdump(data,D,F,A,tape_logical,T);
}
}
// сортировка данных
{
int index=0;
field *datanew=malloc(sizeof(field)*datasize);
tapesinit();
while(index<linecount)
{
int i;
int idx=taperead(tape_logical[0]);
for(i=0;i<selectfieldscount;i++)
_strcpy(datanew[index*selectfieldscount+i],data[idx-keyfieldnum+i]);
index++;
}
_memcpy(data,datanew,sizeof(field)*datasize);
free(datanew);
}
tapesclose();
return 0;
}
typedef void FILE;
typedef unsigned int size_t;
#define EOF -1
// CRT {
int feof( FILE *stream );
int fgetc( FILE *stream );
FILE *fopen( const char *filename, const char *mode );
size_t fwrite( const void *buffer, size_t size, size_t count, FILE *stream );
int fclose( FILE *stream );
size_t fread( void *buffer, size_t size, size_t count, FILE *stream );
int printf( const char *format , ... );
int getc( FILE *stream );
int getchar();
// } CRT
// Addin {
// получает строчку со стандартного устройста ввода
char *_gets( char *buffer,int buffermax);
// записывает строчку оканчивующуся нулем в файл
size_t fwritestring(FILE*,const char*);
// } Addin
#include "stdio.h"
#include "stdlib.h"
size_t fwritestring(FILE* file,const char*p)
{
return fwrite(p,sizeof(char),_strlen(p),file);
}
char *_gets( char *buffer,int buffermax)
{
int i;
buffermax--;
while((i=getchar())!=EOF)
{
if(i==0x0a)
break;
*buffer++=i;
if(--buffermax==0)
break;
}
*buffer=0;
return buffer;
}
#include "types.h"
// CRT {
void * malloc(unsigned);
void free(void*);
double atof(const char*);
// } CRT
// 0 - different ; 1 - eq
int _streq(const char*,const char*);
int _strncmp(const char* i,const char* ii,int count);
// определяет строчку по типу, если это строчка в ковычках - текст.
int _stringformatcmp(const char*,const char*);
int _strcmp(const char *, const char *);
int _strcpy(char*,const char*);
int _strlen(const char*);
void * _memcpy( void *dest, const void *src, int count );
void * _memset( void *dest, int c, int count );
// ищет в массиве flds поля what, возвращает его индекс
int findinarray(fieldname * flds,const char* what);
int findinnumarray(int * flds,int fldscount,int what);
#include "stdlib.h"
int _streq(const char* i,const char* ii)
{
while(*i++==*ii++)
{
if(*i==0&&*ii==0)
return 1;
}
return 0;
}
#define ISNUMBER(x) (x>='0'&&x<='9'||x==','||x=='.'||x=='-')
// орпеделяет есть ли буквы во входной строчке
int haveletters(const char* i)
{
while(*i!=0)
{
if(!ISNUMBER(*i))
return 1;
}
return 0;
}
int _stringformatcmp(const char* i,const char* ii)
{
if(*i=='"'&&*ii=='"')
return _strcmp(i,ii);
if(*i=='"')
return _strncmp(i+1,ii,_strlen(i)-2);
if(*ii=='"')
return _strncmp(i,ii+1,_strlen(ii)-2);
if(haveletters(i)||haveletters(ii))
return _strcmp(i,ii);
return atof(i)<atof(ii);
}
int _strcmp(const char* i,const char* ii)
{
while(*i==*ii)
{
if(*i==0) // если ровна первая ровна и вторая
return 0;
ii++;
i++;
}
return *i<*ii?-1:1;
}
int _strncmp(const char* i,const char* ii,int count)
{
while(*i==*ii&&count--)
{
if(*i==0) // если ровна первая ровна и вторая
return 0;
ii++;
i++;
}
return count==0?0:*i<*ii?-1:1;
}
int _strcpy(char* p,const char* pp)
{
while(*p++=*pp++)
;
return 1;
}
int _strlen(const char* p)
{
int len=0;
while(*p++)
len++;
return len;
}
int findinnumarray(int * flds,int fldscount,int what)
{
int i;
for(i=0;i<fldscount;i++)
{
if(flds[i]==what)
return i;
}
return -1;
}
int findinarray(fieldname * flds,const char* what)
{
int count=0;
while(!_streq(*flds++,what))
count++;
return count;
}
void * _memcpy( void *dest, const void *src, int count )
{
unsigned char *d=(unsigned char *)dest,*s=(unsigned char *)src;
while(count--)
*d++=*s++;
return 0;
}
void * _memset( void *dest, int c, int count )
{
unsigned char *d=(unsigned char *)dest;
while(count--)
*d++=c;
return 0;
}
#include "types.h"
#include "parse.h"
#include "select.h"
#include "sort.h"
#include "show.h"
#include "error.h"
#include "stdio.h"
#include "stdlib.h"
int main()
{
fieldname selectfields[32]={0}; // имена полей по которым идет запрос
int selectfieldsidx[32]={0}; // индексы полей по кторомыи идет запрос (номера по порядку файловых заголовков)
int selectfieldscount;
fieldname orderfield={0}; // имя поля по которому сортируют
// его индекс (номер поля в базе из которой идет запрос, он совпадет
// с одним из индексом из selectfieldsidx.
int orderfieldidx;
// имена файлов-базданных из которых будет браться запрос.
tablename tbls[32]={0};
const int datamaxsize=32768;
int datasize=0;
field *data=(field*)malloc(sizeof(field)*datamaxsize);
//char cmdline[1024]="select header2,header3,header1 from base.csv,base3.csv order by header3";
char cmdline[1024]="select * from material_w1251.txt order by UNIT";
char outputname[260]="baseout.csv";
printf("enter select:\n");
_gets(cmdline,sizeof(cmdline));
printf("enter output file:\n");
_gets(outputname,sizeof(outputname));
if(!parse(selectfields,sizeof(selectfields)/sizeof(fieldname),tbls,sizeof(tbls)/sizeof(tablename),&orderfield,cmdline))
goto error;
if(!normalizeparams(selectfields,&orderfield,tbls,selectfieldsidx,&selectfieldscount,&orderfieldidx))
goto error;
if((datasize=select(selectfieldsidx,selectfieldscount,tbls,data,datamaxsize))==-1)
goto error;
if(sort(data,datasize,selectfieldsidx,selectfieldscount,orderfieldidx))
goto error;
if(!show(data,selectfieldsidx,selectfieldscount,orderfieldidx,outputname))
goto error;
free(data);
return 0;
error:
free(data);
printf("Stage fatal error: '%s'\n",geterror());
return 1;
}
// select * from adfas order by 1,2
/*
I parse разберает строчку
II load грузит указанные поля
III sort сортирует
IV выводит
fields
table
orders
*/